package cs348a.opengl;

import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;

import javax.media.opengl.GLJPanel;
import javax.swing.JPanel;

import com.sun.opengl.util.FPSAnimator;

import cs348a.opengl.object.OpenGLObject;

public class JoglPanel extends JPanel{
	/** The default frames per second value */
	static public int DEFAULT_FPS = 15;
	
	/** Panel */
	private GLJPanel glPanel;
	
	/** OpenGL event listener */
	private JoglEventListener glEventListener;
	
	/** Animator */
	private FPSAnimator animator;
	
	/**
	 * Constructor
	 */
	public JoglPanel() {
		setOpaque(true);
		
		initComponents();
		
		buildPanel();
	}

	/**
	 * Initializes the components.
	 */
	private void initComponents() {
		glEventListener = new JoglEventListener();
		
		glPanel = new GLJPanel();
		glPanel.addGLEventListener(glEventListener);
	}

	/**
	 * Builds the panel.
	 */
	private void buildPanel() {
		setLayout(new BorderLayout());
		
		add(glPanel, BorderLayout.CENTER);
	}
	
	/**
	 * Start animation.
	 * 
	 * @param fps
	 */
	public void startAnimation(int fps) {
		animator = new FPSAnimator(glPanel, fps);
		animator.start();
	}
	
	/**
	 * Start animation. Uses the default FPS.
	 */
	public void startAnimation(){
		startAnimation(DEFAULT_FPS);
	}
	
	/**
	 * 
	 * Stop animation.
	 * 
	 * @param timeOut - in milliseconds
	 * @return true is animation has stopped. false if it has not.
	 */
	public boolean stopAnimation(int timeOut) {
		animator.stop();
		
		long start = System.currentTimeMillis();
		long now = System.currentTimeMillis();
		
		while(animator.isAnimating() || now-start < timeOut){
			now = System.currentTimeMillis();
		}
		
		return !animator.isAnimating();
	}
	
	/**
	 * Returns the rotation of the world
	 * 
	 * @return
	 */
	public float[] rotation() {
		return glEventListener.rotation.clone();
	}
	
	/**
	 * Sets the rotation
	 * 
	 * @param r
	 */
	public void rotateWorld(float[] r) {
		glEventListener.rotation = r.clone();
	}
	
	/**
	 * Returns a handle to the perspective
	 * 
	 * @return
	 */
	public JoglPerspective perspective() {
		return glEventListener.perspective;
	}
	
	/**
	 * Returns a handle to the light
	 * 
	 * @return
	 */
	public JoglLight light() {
		return glEventListener.light;
	}
	
	/**
	 * Adds an <code>OpenGLObject</code>.
	 * 
	 * @param object
	 */
	public void addGLObject(OpenGLObject object){
		glEventListener.addOpenGLObject(object);
	}
	
	/**
	 * Removes the <code>OpenGLObject</code>.
	 * 
	 * @param object
	 */
	public void removeGLObject(OpenGLObject object){
		glEventListener.removeOpenGLObject(object);
	}
	
	/**
	 * Removes all <code>OpenGLObject</code>s.
	 */
	public void removeAllGLObjects(){
		glEventListener.removeAllOpenGLObjects();
	}
	
	/**
	 * Adds the mouse adapter.
	 * 
	 * @param ma
	 */
	public void addMouseAdapter(MouseAdapter ma){
		glPanel.addMouseListener(ma);
		glPanel.addMouseWheelListener(ma);
		glPanel.addMouseMotionListener(ma);
	}
	
	/**
	 * Removes the mouse adapter.
	 * 
	 * @param ma
	 */
	public void removeMouseAdapter(MouseAdapter ma){
		glPanel.removeMouseListener(ma);
		glPanel.removeMouseWheelListener(ma);
		glPanel.removeMouseMotionListener(ma);
	}
}
